import websocket
import threading
import random
from typing import Optional
from PyQt6.QtCore import QObject, pyqtSignal, QTimer
from tools import message_parser, message_processor, message_validator

class WebSocketClient(QObject):
    # 定义信号
    message_received = pyqtSignal(str, str)  # user_name, message
    connection_status_changed = pyqtSignal(str, bool)  # user_name, is_connected
    consent_finished = pyqtSignal()  # 群邀请同意完成信号
    
    def __init__(self):
        super().__init__()
        self.connections = {}  # {user_name: websocket.WebSocketApp}
        self.auto_consent_status = {}  # {user_name: bool}
        self.consent_tasks = []  # 同意进群任务列表
        self.consent_lock = threading.Lock()
        self.consent_timer = None  # 用于存储PyQt定时器对象
        self.interval_seconds = 60  # 固定间隔时间（秒）
        
        # 初始化时加载待处理的任务
        self.load_pending_tasks()

    def set_auto_consent_status(self, user_name: str, enabled: bool):
        """设置指定用户的自动同意进群状态"""
        self.auto_consent_status[user_name] = enabled
        print(f"用户 {user_name} 的自动同意状态已设置为: {'启用' if enabled else '禁用'}")
    
    def set_interval_seconds(self, seconds: int):
        """设置固定间隔时间（秒）"""
        try:
            if seconds < 0 or seconds > 60:
                print(f"⚠️ 间隔时间超出范围 (0-60秒): {seconds}秒")
                return False
            
            self.interval_seconds = seconds
            print(f"✅ 间隔时间已设置为: {seconds}秒")
            
            # 如果定时器正在运行，重新启动以应用新间隔
            if self.consent_timer and self.consent_timer.isActive():
                print(f"🔄 重新启动定时器以应用新间隔: {seconds}秒")
                self.start_consent_timer()
            
            return True
        except Exception as e:
            print(f"❌ 设置间隔时间时出错: {e}")
            return False
    
    def start_consent_timer(self):
        """启动同意进群定时器"""
        try:
            # 如果已有定时器在运行，先停止它
            if self.consent_timer and self.consent_timer.isActive():
                self.consent_timer.stop()
                
            interval = self.interval_seconds * 1000  # 转换为毫秒
            
            print(f"⏰ 启动同意进群定时器，间隔: {interval/1000:.1f}秒")
            
            self.consent_timer = QTimer()
            self.consent_timer.setInterval(interval)
            self.consent_timer.timeout.connect(self._process_consent_queue)
            self.consent_timer.start()
            
        except Exception as e:
            print(f"❌ 启动同意进群定时器时出错: {e}")
            
    def stop_consent_timer(self):
        """停止同意进群定时器"""
        try:
            if self.consent_timer:
                if self.consent_timer.isActive():
                    self.consent_timer.stop()
                self.consent_timer.deleteLater()
                self.consent_timer = None
                print("⏹️ 停止同意进群定时器")
        except Exception as e:
            print(f"❌ 停止同意进群定时器时出错: {e}")
    
    def _process_consent_queue(self):
        """处理同意进群队列"""
        try:
            with self.consent_lock:
                if not self.consent_tasks:
                    print(f"📭 队列为空，停止同意进群定时器")
                    self.stop_consent_timer()
                    return
                
                # 随机打乱任务顺序，避免被检测到固定模式
                random.shuffle(self.consent_tasks)
                print(f"🔄 已随机打乱任务顺序，当前任务数量: {len(self.consent_tasks)}")
                
                # 取出一个任务进行处理（一次只处理一个任务）
                task = self.consent_tasks.pop(0)
            
            # 处理单个任务
            user_name = task['user_name']
            invite_info = task['invite_info']
            
            print(f"🔄 处理同意进群任务 - {user_name}")
            print(f"   群名称: {invite_info.get('group_name', '未知')}")
            print(f"   邀请人: {invite_info.get('inviter_nickname', '未知')}")
            
            self._execute_consent_to_join_group(user_name, invite_info)
            
            print(f"✅ 任务处理完成")
            
            # 检查是否还有更多任务需要处理
            with self.consent_lock:
                if self.consent_tasks:
                    print(f"📋 队列中还有 {len(self.consent_tasks)} 个任务，等待间隔时间后继续处理...")
                    # 等待指定的间隔时间后再处理下一个任务
                    # 这样可以确保任务之间的间隔是从上一个任务结束后开始计算的
                    QTimer.singleShot(self.interval_seconds * 1000, self.start_consent_timer)
                else:
                    print(f"📭 队列已清空，停止同意进群定时器")
                    self.stop_consent_timer()
            
        except Exception as e:
            print(f"❌ 处理同意进群队列时出错: {e}")
            # 出错时也停止定时器，避免无限循环
            self.stop_consent_timer()
    
    def connect_user(self, user_name: str):
        """为指定用户建立WebSocket连接，用于接收消息数据"""
        # 如果已经连接，先断开
        if user_name in self.connections:
            self.disconnect_user(user_name)
        
        # 在新线程中运行WebSocket连接
        thread = threading.Thread(target=self._connect_websocket, args=(user_name,))
        thread.daemon = True
        thread.start()
    
    def _connect_websocket(self, user_name: str):
        """在新线程中建立WebSocket连接"""
        ws_url = f"ws://47.122.123.157:8088/ws/{user_name}"
        
        try:
            print(f"正在连接WebSocket: {ws_url}")
            
            # 创建WebSocket连接，添加超时设置
            ws = websocket.WebSocketApp(
                ws_url,
                on_open=lambda ws: self._on_open(ws),
                on_message=lambda ws, msg: self._on_message(ws, msg),
                on_error=lambda ws, error: self._on_error(ws, error),
                on_close=lambda ws, close_status_code, close_msg: self._on_close(ws, close_status_code, close_msg)
            )
            
            # 存储WebSocket对象
            self.connections[user_name] = ws
            
            # 在新线程中运行WebSocket，添加超时设置
            try:
                ws.run_forever(ping_interval=30, ping_timeout=10)
            except Exception as e:
                print(f"WebSocket运行出错 - {user_name}: {e}")
                
        except Exception as e:
            print(f"WebSocket连接失败 - {user_name}: {e}")
        finally:
            # 从连接列表中移除
            try:
                if user_name in self.connections:
                    del self.connections[user_name]
            except Exception as e:
                print(f"清理WebSocket连接时出错 - {user_name}: {e}")
    
    def _on_message(self, ws, message):
        """处理WebSocket消息"""
        try:
            user_name = self._get_user_name_from_ws(ws)
            if not user_name:
                print("⚠️ 无法从WebSocket连接获取用户名")
                return
            
            # 发射消息接收信号
            self.message_received.emit(user_name, message)
            
            # 处理消息
            self._process_message(user_name, message)
            
        except Exception as e:
            print(f"❌ 处理WebSocket消息时出错: {e}")
    
    def _on_open(self, ws):
        """WebSocket连接打开时的回调"""
        try:
            user_name = self._get_user_name_from_ws(ws)
            if not user_name:
                print("⚠️ 无法从WebSocket连接获取用户名")
                return
            
            print(f"🔗 WebSocket连接已建立 - {user_name}")
            
            # 发射连接状态变化信号
            self.connection_status_changed.emit(user_name, True)
            
        except Exception as e:
            print(f"❌ WebSocket连接打开回调出错: {e}")
    
    def _on_error(self, ws, error):
        """WebSocket连接错误时的回调"""
        try:
            user_name = self._get_user_name_from_ws(ws)
            if not user_name:
                print("⚠️ 无法从WebSocket连接获取用户名")
                return
            
            print(f"❌ WebSocket连接错误 - {user_name}: {error}")
            
            # 发射连接状态变化信号
            self.connection_status_changed.emit(user_name, False)
            
        except Exception as e:
            print(f"❌ WebSocket连接错误回调出错: {e}")
    
    def _on_close(self, ws, close_status_code, close_msg):
        """WebSocket连接关闭时的回调"""
        try:
            user_name = self._get_user_name_from_ws(ws)
            if not user_name:
                print("⚠️ 无法从WebSocket连接获取用户名")
                return
            
            print(f"🔌 WebSocket连接已关闭 - {user_name}: {close_status_code} - {close_msg}")
            
            # 发射连接状态变化信号
            self.connection_status_changed.emit(user_name, False)
            
        except Exception as e:
            print(f"❌ WebSocket连接关闭回调出错: {e}")
    
    def _process_message(self, user_name: str, message):
        """处理接收到的消息，解析群邀请并回复"""
        try:
            if not message or message == "":
                return
            
            # 特判：纯文本状态消息 "wxid_xxx已连接..." → 视为该账号已连接
            if isinstance(message, str) and ("已连接" in message) and not message.strip().startswith('{'):
                account_id = message.split('已连接')[0].strip()
                if account_id:
                    print(f"📶 状态消息：{account_id} 已连接")
                    # 更新数据库状态为在线
                    try:
                        from database import db_manager
                        db_manager.update_account_status(account_id, 1)
                    except Exception as e:
                        print(f"更新数据库在线状态失败: {account_id}, 错误: {e}")
                    return
            
            # 处理可能包含多个JSON对象的消息
            self._process_multiple_json_messages(user_name, message)
                
        except Exception as e:
            print(f"处理消息时出错 - {user_name}: {e}")
            print(f"原始消息: {message[:200]}...")  # 显示前200个字符用于调试
    
    def _process_multiple_json_messages(self, user_name: str, message: str):
        """处理可能包含多个JSON对象的消息"""
        try:
            # 尝试解析为单个JSON对象
            try:
                message_data = message_parser.parse_message(message)
                if message_data:
                    self._process_single_message(user_name, message_data)
                    return
            except:
                pass
            
            # 如果不是单个JSON，尝试分割多个JSON对象
            json_objects = self._split_json_objects(message)
            
            if len(json_objects) > 1:
                print(f"🔍 检测到 {len(json_objects)} 个JSON对象，分别处理...")
                
                for i, json_str in enumerate(json_objects):
                    try:
                        print(f"📝 处理第 {i+1} 个JSON对象...")
                        message_data = message_parser.parse_message(json_str)
                        if message_data:
                            self._process_single_message(user_name, message_data)
                        else:
                            print(f"⚠️ 第 {i+1} 个JSON对象解析失败: {json_str[:100]}...")
                    except Exception as e:
                        print(f"❌ 处理第 {i+1} 个JSON对象时出错: {e}")
                        print(f"   内容: {json_str[:100]}...")
            else:
                print(f"⚠️ 无法识别消息格式，可能是无效的JSON: {message[:100]}...")
                
        except Exception as e:
            print(f"处理多JSON消息时出错 - {user_name}: {e}")
    
    def _split_json_objects(self, message: str) -> list:
        """分割包含多个JSON对象的消息"""
        json_objects = []
        current_pos = 0
        brace_count = 0
        start_pos = -1
        
        for i, char in enumerate(message):
            if char == '{':
                if brace_count == 0:
                    start_pos = i
                brace_count += 1
            elif char == '}':
                brace_count -= 1
                if brace_count == 0 and start_pos != -1:
                    # 找到一个完整的JSON对象
                    json_str = message[start_pos:i+1].strip()
                    if json_str:
                        json_objects.append(json_str)
                    start_pos = -1
        
        # 如果没有找到完整的JSON对象，尝试其他分割方法
        if not json_objects:
            # 尝试按换行符分割
            lines = message.strip().split('\n')
            for line in lines:
                line = line.strip()
                if line.startswith('{') and line.endswith('}'):
                    try:
                        # 验证是否为有效JSON
                        import json
                        json.loads(line)
                        json_objects.append(line)
                    except:
                        continue
        
        return json_objects
    
    def _process_single_message(self, user_name: str, message_data: dict):
        """处理单个消息数据"""
        try:
            # 验证消息格式
            if not message_validator.validate_message_format(message_data):
                print(f"消息格式验证失败 - {user_name}")
                return
            
            # 检查是否是群邀请消息
            if message_parser.is_group_invite_message(message_data):
                print(f"检测到群邀请消息 - {user_name}")
                self._handle_group_invite(user_name, message_data)
            else:
                print(f"收到非群邀请消息 - {user_name}: {type(message_data).__name__}")
                
        except Exception as e:
            print(f"处理单个消息时出错 - {user_name}: {e}")
    
    def _handle_group_invite(self, user_name: str, message_data: dict):
        """处理群邀请消息并存储"""
        try:
            # 使用工具函数处理群邀请消息
            invite_info = message_processor.process_group_invite(user_name, message_data)
            if not invite_info:
                return
            
            # 自动同意进群（在新线程中执行，避免阻塞WebSocket）
            self._auto_consent_to_join_group(user_name, invite_info)
            self.consent_finished.emit()  # 收到邀请后立即刷新table
            
        except Exception as e:
            print(f"处理群邀请时出错 - {user_name}: {e}")
    
    def _auto_consent_to_join_group(self, user_name: str, invite_info: dict):
        """自动同意进群（添加到队列，使用定时器控制间隔）"""
        try:
            # 检查用户是否启用了自动同意功能
            if not self.auto_consent_status.get(user_name, True):
                print(f"🚫 用户 {user_name} 已关闭自动同意功能，跳过群邀请")
                print(f"   群名称: {invite_info.get('group_name', '未知')}")
                print(f"   邀请人: {invite_info.get('inviter_nickname', '未知')}")
                return
            
            # 先保存邀请明细到数据库，包括invite_url
            try:
                from database import db_manager
                group_name = invite_info.get('group_name', '未知')
                invite_url = invite_info.get('invite_url', '')
                
                # 保存邀请明细，状态为"等待中"
                db_manager.add_invite_detail(
                    user_name=user_name,
                    group_name=group_name,
                    invite_url=invite_url,
                    invite_result="等待中",
                    remark=f"已添加到处理队列 - {invite_info.get('inviter_nickname', '未知')}"
                )
                print(f"✅ 邀请明细已保存到数据库 - {user_name}, 群名: {group_name}")
            except Exception as e:
                print(f"❌ 保存邀请明细到数据库失败 - {user_name}: {e}")
            
            # 将任务添加到队列
            task = {
                'user_name': user_name,
                'invite_info': invite_info
            }
            
            with self.consent_lock:
                self.consent_tasks.append(task)
            
            print(f"📋 同意进群任务已添加到队列 - {user_name}")
            print(f"   群名称: {invite_info.get('group_name', '未知')}")
            print(f"   邀请人: {invite_info.get('inviter_nickname', '未知')}")
            print(f"   当前队列大小: {len(self.consent_tasks)}")
            
            # 启动定时器（如果还没有启动）
            self.start_consent_timer()
            
        except Exception as e:
            print(f"❌ 添加同意进群任务到队列时出错 - {user_name}: {e}")
    
    def _execute_consent_to_join_group(self, user_name: str, invite_info: dict):
        """执行同意进群操作"""
        try:
            group_name = invite_info.get('group_name', '未知')
            inviter_name = invite_info.get('inviter_nickname', '未知')
            
            print(f"🔄 执行同意进群操作 - {user_name}")
            print(f"   群名称: {group_name}")
            print(f"   邀请人: {inviter_name}")
            
            # 获取邀请链接
            invite_url = invite_info.get('invite_url', '')
            if not invite_url:
                print(f"❌ 群邀请链接为空 - {user_name}, 群名: {group_name}")
                return
            
            print(f"🔗 邀请链接: {invite_url}")
            
            # 验证邀请链接格式
            if not invite_url.startswith('http'):
                print(f"❌ 邀请链接格式无效 - {user_name}, 链接: {invite_url}")
                return
            
            # 调用同意进群API
            print(f"📡 正在调用同意进群API - {user_name}, 群名: {group_name}")
            # 使用延迟导入避免循环导入
            import http_client
            result = http_client.http_client.consent_to_join_group(user_name, invite_url)
            
            print(f"📊 API响应: {result}")
            
            if result.get('Code') == 0 and result.get('Success', False):
                print(f"✅ 自动同意进群成功 - {user_name}")
                print(f"   群名称: {group_name}")
                print(f"   邀请人: {inviter_name}")
                print(f"   消息ID: {invite_info.get('msg_id', '未知')}")

                # 移动到联系人列表
                qid = result.get('Data', '')
                http_client.http_client.move_contract_list(qid, user_name)
                
                # 保存群聊信息到数据库
                try:
                    from database import db_manager
                    # 添加群聊记录
                    db_manager.add_user_group(
                        user_name=user_name,
                        qid=qid,
                        group_name=group_name,
                        inviter_name=inviter_name,
                        remark=f"自动同意成功 - {inviter_name}"
                    )
                    print(f"✅ 群聊记录已保存到数据库 - {user_name}, 群名: {group_name}, qid: {qid}")
                except Exception as e:
                    print(f"❌ 保存群聊记录失败 - {user_name}: {e}")
                
                # 更新数据库中的邀请结果
                try:
                    from database import db_manager
                    # 使用invite_url来更新邀请结果，确保找到正确的记录
                    db_manager.update_invite_detail_by_url(
                        user_name=user_name,
                        invite_url=invite_url,
                        invite_result='已同意',
                        remark=f"自动同意成功 - {inviter_name}"
                    )
                    print(f"✅ 数据库邀请结果已更新 - {user_name}, 群名: {group_name}")
                except Exception as e:
                    print(f"❌ 更新数据库邀请结果失败 - {user_name}: {e}")
                
                # 触发UI刷新
                self.consent_finished.emit()  # 同意成功后刷新table
            else:
                error_msg = result.get('Message', '未知错误')
                print(f"❌ 自动同意进群失败 - {user_name}")
                print(f"   群名称: {group_name}")
                print(f"   邀请人: {inviter_name}")
                print(f"   错误信息: {error_msg}")
                print(f"   响应代码: {result.get('Code', '未知')}")
                
                # 更新数据库中的邀请结果
                try:
                    from database import db_manager
                    # 使用invite_url来更新邀请结果，确保找到正确的记录
                    db_manager.update_invite_detail_by_url(
                        user_name=user_name,
                        invite_url=invite_url,
                        invite_result='失败',
                        remark=f"同意失败: {error_msg}"
                    )
                    print(f"✅ 数据库邀请结果已更新 - {user_name}, 群名: {group_name}")
                except Exception as e:
                    print(f"❌ 更新数据库邀请结果失败 - {user_name}: {e}")
                
                self.consent_finished.emit()  # 同意失败后也刷新table
                
        except Exception as e:
            print(f"❌ 执行同意进群操作时出错 - {user_name}: {e}")
            print(f"   群名称: {invite_info.get('group_name', '未知')}")
            print(f"   邀请人: {invite_info.get('inviter_nickname', '未知')}")
    
    def _get_user_name_from_ws(self, ws) -> Optional[str]:
        """从WebSocket连接对象获取用户名"""
        for user_name, ws_app in self.connections.items():
            if ws_app == ws:
                return user_name
        return None
    
    def disconnect_user(self, user_name: str):
        """断开指定用户的WebSocket连接"""
        if user_name in self.connections:
            try:
                ws = self.connections[user_name]
                if ws is not None:
                    ws.close()
                    print(f"正在断开WebSocket连接: {user_name}")
                        
                # 清理资源
                try:
                    if user_name in self.connections:
                        del self.connections[user_name]
                except Exception as e:
                    print(f"清理WebSocket资源时出错 - {user_name}: {e}")
                    
            except Exception as e:
                print(f"断开WebSocket连接时出错 - {user_name}: {e}")
                # 即使出错也要清理资源
                try:
                    if user_name in self.connections:
                        del self.connections[user_name]
                except:
                    pass
    
    def get_connection_status(self, user_name: str) -> dict:
        """获取指定用户的连接状态信息"""
        try:
            if user_name in self.connections:
                ws = self.connections[user_name]
                # 检查WebSocket对象是否有效
                if ws is not None:
                    return {
                        "connected": True,
                        "url": f"ws://47.122.123.157:8088/ws/{user_name}"
                    }
                else:
                    # WebSocket对象为None，视为未连接
                    return {
                        "connected": False,
                        "url": f"ws://47.122.123.157:8088/ws/{user_name}",
                        "error": "WebSocket对象为None"
                    }
            else:
                return {
                    "connected": False,
                    "url": f"ws://47.122.123.157:8088/ws/{user_name}"
                }
        except Exception as e:
            print(f"获取用户 {user_name} 连接状态时出错: {e}")
            return {
                "connected": False,
                "url": f"ws://47.122.123.157:8088/ws/{user_name}",
                "error": str(e)
            }

    def get_consent_queue_size(self) -> int:
        """获取同意进群队列大小"""
        with self.consent_lock:
            return len(self.consent_tasks)
    
    def get_all_consent_status(self) -> dict:
        """获取所有同意进群连接状态"""
        return {
            'connections': len(self.connections),
            'queue_size': self.get_consent_queue_size(),
            'interval_seconds': self.interval_seconds,
            'auto_consent_status': self.auto_consent_status.copy()
        }
    
    def is_connected(self, user_name: str) -> bool:
        """检查指定用户是否已连接"""
        try:
            if user_name in self.connections:
                ws = self.connections[user_name]
                return ws is not None
            return False
        except Exception as e:
            print(f"检查用户 {user_name} 连接状态时出错: {e}")
            return False
    
    def get_all_connection_status(self) -> dict:
        """获取所有连接状态"""
        try:
            status = {}
            for user_name in self.connections:
                status[user_name] = self.get_connection_status(user_name)
            return status
        except Exception as e:
            print(f"获取所有连接状态时出错: {e}")
            return {}

    def load_pending_tasks(self):
        """加载未完成的任务"""
        try:
            from database import db_manager
            pending_tasks = db_manager.get_pending_invites()
            if pending_tasks:
                print(f"🔄 加载到 {len(pending_tasks)} 个未完成的同意进群任务")
                for task in pending_tasks:
                    user_name = task['user_name']
                    invite_info = {
                        'group_name': task['group_name'],
                        'inviter_nickname': '未知',  # 从备注中提取或使用默认值
                        'invite_url': task['invite_url'],
                        'msg_id': 'unknown'  # 重启后无法获取原始消息ID
                    }
                    
                    # 检查用户是否开启了自动同意功能
                    if self.auto_consent_status.get(user_name, True):
                        self._auto_consent_to_join_group(user_name, invite_info)
                        print(f"✅ 已重新添加任务到队列 - {user_name}, 群名: {task['group_name']}")
                    else:
                        print(f"ℹ️ 用户 {user_name} 未开启自动同意功能，跳过未完成任务")
            else:
                print("ℹ️ 没有未完成的同意进群任务")
        except Exception as e:
            print(f"❌ 加载未完成任务时出错: {e}")

# 全局WebSocket客户端实例
websocket_client = WebSocketClient() 